#define _CRT_SECURE_NO_WARNINGS 1

//#include <stdio.h>
//#include <string.h>
//
//// gets一般用来读入字符串
//int main()
//{
//	char str[10] = { 0 };
//	gets(str);
//	printf("%s", str);
//
//	return 0;
//}

//#include <stdio.h>
//#include <string.h>
//
//void Reverse(char* left, char* right)
//{
//	while (left < right) {
//		char tmp = *left;
//		*left = *right;
//		*right = tmp;
//
//		left++;
//		right--;
//	}
//}
//
//void leftRev1(char* str, int k)
//{
//
//	int len = k % strlen(str);
//	if (len == 0) return;
//	
//	Reverse(str, str + (len - 1));
//	Reverse(str + len, str + strlen(str) - 1);
//	Reverse(str, str + strlen(str) - 1);
//}
//
//void leftRev2(char* str, int time)
//{
//	// 确定挪动几次
//	int len = strlen(str);
//	int count = time % len;
//
//	// 挪动元素
//	for (int i = 0; i < time; i++) {
//		char tmp = str[0];
//		// 开始挪动
//		for (int j = 0; j < len - 1; j++) {
//			str[j] = str[j + 1];
//		}
//		str[len - 1] = tmp;
//	}
//}
//
//int main()
//{
//	char str[10] = { 0 };
//	gets(str);
//
//	//leftRev1(str, 5);
//	//printf("%s\n", str);
//
//	//leftRev2(str, 5);
//	//printf("%s\n", str);
//
//	return 0;
//}

//#include <stdio.h>

//int main()
//{
//	//二维数组也是数组，之前对数组名理解也是适合
//	int a[3][4] = { 0 };
//	printf("%zd\n", sizeof(a));//12*4 = 48个字节，数组名单独放在sizeof内部
//	printf("%zd\n", sizeof(a[0][0]));//4
//	printf("%zd\n", sizeof(a[0]));//a[0]是第一行这个一维数组的数组名，数组名单独放在sizeof内部了
//	//计算的是第一行的大小，单位是字节，16个字节
//
//	printf("%zd\n", sizeof(a[0] + 1));//a[0]第一行这个一维数组的数组名,这里表示数组首元素
//	//也就是a[0][0]的地址，a[0] + 1是a[0][1]的地址 4/8
//
//	printf("%zd\n", sizeof(*(a[0] + 1)));//a[0][1] - 4个字节
//	printf("%zd\n", sizeof(a + 1));//a是二维数组的数组名，但是没有&，也没有单独放在sizeof内部
//	//所以这里的a是数组收元素的地址，应该是第一行的地址，a+1是第二行的地址
//	//大小也是4/8 个字节
//	printf("%zd\n", sizeof(*(a + 1)));//*(a + 1) ==> a[1] - 第二行的数组名，单独放在sizeof内部，计算的是第二行的大小
//	//16个字节
//	printf("%zd\n", sizeof(&a[0] + 1));//&a[0]是第一行的地址，&a[0]+1就是第二行的地址，4/8
//	printf("%zd\n", sizeof(*(&a[0] + 1)));//访问的是第二行，计算的是第二行的大小，16个字节
//	//int(*p)[4] = &a[0] + 1;
//	//
//	printf("%zd\n", sizeof(*a));//这里的a是第一行的地址，*a就是第一行，sizeof(*a)计算的是第一行的大小-16
//	//*a --> *(a+0) --> a[0]
//	printf("%zd\n", sizeof(a[3]));//这里不存在越界
//	//因为sizeof内部的表达式不会真实计算的
//	//计算的是第四行的大小-16
//
//	return 0;
//}

//在X86环境下
//假设结构体的大小是20个字节
//程序输出的结果是啥？

//
//#include <stdio.h>
//struct Test
//{
//    int Num;
//    char* pcName;
//    short sDate;
//    char cha[2];
//    short sBa[4];
//}* p = (struct Test*)0x100000;
////
////指针+整数
////
//int main()
//{
//    printf("%p\n", p + 0x1); //0x100000+20 == 0x100014
//    printf("%p\n", (unsigned long)p + 0x1);//0x100000+1 == 0x100001
//    printf("%p\n", (unsigned int*)p + 0x1);//0x100000+1 == 0x100004
//    return 0;
//}

//#include <stdio.h>
//
//int main()
//{
//	int a[3][2] = { (0,1),(2,3),(4,5) }; // 注意圆括号，且逗号表达式
//	int* p = a[0];
//	printf("%d", p[0]);
//
//	return 0;
//}

//#include <stdio.h>
//
//int main()
//{
//	int aa[2][5] = { 1,2,3,4,5,6,7,8,9,10 };
//
//	int* ptr1 = (int*)(&aa + 1);
//	int* ptr2 = (int*)(*(aa + 1));
//
//	printf("%d %d", *(ptr1 - 1), *(ptr2 - 1));
//
//	return 0;
//}

//#include <stdio.h>
//
//int main()
//{
//	char* a[] = { "work", "at", "alibaba" };
//	char** pa = a;
//
//	pa++;
//	printf("%s\n", *pa);
//
//	return 0;
//}

//#include <stdio.h>
//
//int main()
//{
//	char* c[] = { "ENTER", "NEW", "POINT", "FIRST" };
//	char** cp[] = { c + 3, c + 2, c + 1, c };
//	char*** cpp = cp;
//
//	printf("%s\n", **++cpp); // POINT
//	printf("%s\n", *-- * ++cpp + 3); // ER +号的优先级很低
//	printf("%s\n", *cpp[-2] + 3); // ST cpp[-2] == *(cpp - 2)
//	printf("%s\n", cpp[-1][-1] + 1);// EW 
//
//	return 0;
//}

// 字符串相关函数
//#include <stdio.h>
//#include <string.h>
//
//int main()
//{
//	char arr[] = "abcdef"; // a b c d e f \0
//	size_t len = strlen(arr);
//
//	printf("%zd\n", len);
//
//	return 0;
//}

//#include <stdio.h>
//#include <string.h>
//
//// 因为strlen返回的是无符号整型
//// 而-3被当作无符号整型来看的时候是一个非常大的数字
//
//int main()
//{
//	if (strlen("abc") - strlen("abcdef") > 0)
//		printf("大于\n"); // 实际上是大于
//	else printf("小于等于\n");
//
//	return 0;
//}


//// strlen的使用和模拟实现
//#include <stdio.h>
//#include <assert.h>
//
//size_t my_strlen1(const char* str)
//{
//	assert(str != NULL);
//
//	//size_t count = 0;
//	//while (*str != '\0') {
//	//	count++;
//	//	str++;
//	//}
//
//	//return count;
//
//	char* start= str;
//	while (*str != '\0')
//		str++;
//
//	return (size_t)(str - start);
//}
//
//size_t my_strlen2(const char* str)
//{
//	assert(str != NULL);
//
//	if (*str == '\0') return 0;
//	return 1 + my_strlen2(str + 1);
//}
//
//int main()
//{
//	char arr[] = "abcdef";
//
//	size_t len1 = my_strlen1(arr);
//	size_t len2 = my_strlen2(arr);
//	
//	printf("%zd\n", len1);
//	printf("%zd\n", len2);
//
//	return 0;
//}

// strcpy的使用和模拟实现
// char* strcpy(char* destination, const char* source);
// 原字符串必须有字符0，也会复制过去，且目的地字符串必须得空间够
// 目标空间必须可修改
//#include <stdio.h>
//
//int main()
//{
//	char arr1[20] = { 0 };
//	char arr2[] = "Hello";
//
//	strcpy(arr1, arr2);
//	printf("%s\n", arr1);
//	return 0;
//}

//#include <stdio.h>
//#include <string.h>
//
//int main()
//{
//	char* p = "abcdefg";
//	char arr[5] = "xxxx";
//
//	strcpy(p, arr); // err
//	printf("%s\n", p);
//
//	return 0;
//}

//#include <stdio.h>
//#include <string.h>
//#include <assert.h>
//
//char* my_strcpy(char* dest, const char* src)
//{
//	 assert(dest && src);
//
//	 char* ret = dest;
//	 while (*dest++ = *src++) 
//	 {
//	 	;
//	 }
//
//	 return ret;
//}
//
// *src++
//int main()
//{
//	char arr1[20] = { 0 };
//	char arr2[] = "abcdef";
//
//	my_strcpy(arr1, arr2);
//	printf("%s\n", arr1);
//
//	return 0;
//}

// NULL 本质也是0，一般用于指针的初始化
// \0 \ddd形式的转义字符，本质也是0，一般用作字符串的结束标志
// 0 数字0
// nul \0
// '0'字符0，本质上是48

// strcat的使用和模拟实现
// char * strcat ( char * destination, const char * source );
// 找到目标字符串的\0
// 拷贝源头字符串的数据到目标空间的\0位置及后面空间

//#include <stdio.h>
//#include <string.h>
//#include <assert.h>
//
//char* my_strcat(char* dest, const char* src)
//{
//	char* ret = dest;
//	assert(dest && src);
//
//	// 1.找到目标空间的\0
//	while (*dest) dest++;
//	// 2.拷贝
//	while (*dest++ = *src++) { ; }
//
//	return ret;
//}
//
//int main()
//{
//	char arr1[20] = "Hello ";
//	char arr2[] = "World!";
//
//	my_strcat(arr1, arr2);
//	printf("%s\n", arr1);
//
//	return 0;
//}

// strcmp的使用和模拟实现
// int strcmp ( const char * str1, const char * str2 );
// 第一个字符串大于第二个字符串，则返回大于0的数字
// 第一个字符串等于第二个字符串，则返回等于0的数字
// 第一个字符串小于第二个字符串，则返回小于0的数字

#include <stdio.h>
#include <string.h>
#include <assert.h>

//int main()
//{
//	int ret = strcmp("abcdef", "abq");
//	printf("%d\n", ret);
//
//
//	return 0;
//}

//int my_strcmp(const char* s1, const char* s2)
//{
//	while (*s1 == *s2) {
//		if (*s1 == '\0') return 0;
//
//		s1++;
//		s2++;
//	}
//
//	return *s1 - *s2;
//}

//int main()
//{
//	int ret = my_strcmp("abc", "abcdef");
//
//	if (ret > 0) printf("大于\n");
//	else if (ret == 0) printf("等于\n");
//	else printf("小于\n");
//
//	return 0;
//}


// strncpy, strncat, strncmp
//#include <stdio.h>
//#include <string.h>
//#include <assert.h>
//
//int main()
//{
//	char arr1[20] = "xxxxxx";
//	char arr2[] = "Hello";
//
//	// strncpy(arr1, arr2, 3);
//	// strncat(arr1, arr2, 4);
//	// strncmp(arr1, arr2, 4);
//
//	return 0;
//}

//// strstr的使用和模拟实现
//// char* strstr(const char* str1, const char* str2);
//#include <stdio.h>
//#include <string.h>
//#include <assert.h>
//
//char* my_strstr(const char* str1, const char* str2)
//{
//	const char* cur = str1;
//	const char* s1 = NULL, *s2 = NULL;
//
//	assert(str1 && str2);
//
//	if (*str2 == '\0') return (char*)str1;
//	while (*cur)
//	{
//		s1 = cur;
//		s2 = str2;
//
//		while (*s1 && *s2 && *s1 == *s2) {
//			s1++;
//			s2++;
//		}
//
//		if (*s2 == '\0') return (char*)cur;
//		cur++;
//	}
//
//	return NULL;
//}
//
//int main()
//{
//	char arr1[] = "abcdefabcdef";
//	char arr2[] = "def";
//
//	// 找不到就返回空指针
//	char* ret = my_strstr(arr1, arr2);
//
//	if (ret != NULL)
//		printf("%s\n", ret);
//	else printf("找不到\n");
//
//	return 0;
//}





